using Jupiter.Infrastructure;
using Jupiter.Infrastructure.Cache.Interfaces;
using Jupiter.Infrastructure.Domain;
using Jupiter.Infrastructure.Domain.SqlSugar;
using Jupiter.Infrastructure.Domain.SqlSugar.Basic;
using Jupiter.Infrastructure.Exceptions;
using Jupiter.Infrastructure.Mappings;
using Jupiter.Infrastructure.Permission;
using Jupiter.Infrastructure.Permission.DataPermissions;
using MediatR;
using Microsoft.Extensions.Configuration;
using Wips.AppService.Authorities.Organizations.Requests;
using Wips.Domain.Models.Authorities.Model;

namespace Wips.AppService.SqlSugar.Authorities.Organizations;

/// <summary>
/// 组织架构请求处理程序
/// </summary>
public class OrganizationRequestHandler :
    RequestHandlerBase<Organization>,
    IRequestHandler<CreateOrganizationRequest, string>,
    IRequestHandler<UpdateOrganizationRequest, string>,
    IRequestHandler<DeleteOrganizationRequest, string>,
    IRequestHandler<OrganizationStatusChangeRequest, string>,
    IRequestHandler<UpdateOrganizationExtendRequest, string>
{
    private readonly IMapsterMapper _mapper;


    /// <summary>
    /// 创建
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<string> Handle(CreateOrganizationRequest request,
        CancellationToken cancellationToken)
    {
        var entity = _mapper.MapTo<Organization>(request);
        entity.Id = ObjectId.GenerateNewStringId();
        entity.CreatorId = UserId;
        entity.LastUpdatedUserId = UserId;
        if (request.ParentId != null)
        {
            entity.ParentPath = await GetParentPathAsync(request.ParentId, cancellationToken);
        }

        await RegisterNewAsync(entity, cancellationToken);

        // 新增关联数据
        if (request.RoleIds.Count > 0)
        {
            var organizationRoles = request
                .RoleIds
                .Select(roleId =>
                    new OrganizationRole(entity.Id, roleId)
                ).ToList();
            await RegisterNewObjectValueRangeAsync(organizationRoles, cancellationToken: cancellationToken);
        }


        return entity.Id;
    }

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<string> Handle(UpdateOrganizationRequest request,
        CancellationToken cancellationToken)
    {
        if (request.ParentId == request.Id)
        {
            throw new CoreException("不能选择自己作为上级");
        }

        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        if (request.ParentId != null)
        {
            entity.ParentPath = await GetParentPathAsync(request.ParentId, cancellationToken);
        }

        entity.Name = request.Name;
        entity.Remarks = request.Remarks;
        entity.Updated = DateTime.Now;
        entity.LastUpdatedUserId = UserId;
        // 更新
        RegisterDirty(entity);

        RegisterDeleteObjectValueRange<OrganizationRole>(p => p.OrganizationId == entity.Id);

        // 新增关联数据
        if (request.RoleIds.Count > 0)
        {
            var organizationRoles = request
                .RoleIds
                .Select(roleId =>
                    new OrganizationRole(entity.Id, roleId)
                ).ToList();
            await RegisterNewObjectValueRangeAsync(organizationRoles, cancellationToken: cancellationToken);
        }

        return entity.Id!;
    }


    /// <summary>
    /// 删除组织架构
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="CoreException"></exception>
    public async Task<string> Handle(DeleteOrganizationRequest request,
        CancellationToken cancellationToken)
    {
        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);
        if (entity == null)
        {
            throw new CoreException("找不到要删除的数据");
        }

        RegisterDeleteObjectValueRange<OrganizationRole>(p => p.OrganizationId == entity.Id);

        // 删除
        RegisterDelete(entity);

        return entity.Id!;
    }

    /// <summary>
    /// 状态变更
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<string> Handle(OrganizationStatusChangeRequest request,
        CancellationToken cancellationToken)
    {
        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        // 变更状态
        entity.StatusChange(UserId);
        // 更新
        RegisterDirty(entity);

        return entity.Id!;
    }

    #region 私有方法

    /// <summary>
    /// 读取ParentPath
    /// </summary>
    /// <param name="parentId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="CoreException"></exception>
    private async Task<string> GetParentPathAsync(string parentId,
        CancellationToken cancellationToken = default)
    {
        // 读取上级信息
        var parent = await QueryNoTracking()
            .FirstOrDefaultAsync(p => p.Id == parentId, cancellationToken);

        if (parent == null)
        {
            throw new CoreException("找不到上级菜单");
        }

        return string.IsNullOrEmpty(parent.ParentPath)
            ? parentId
            : $"{parent.ParentPath},{parentId}";
    }

    #endregion

    #region 扩展信息

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="CoreException"></exception>
    public async Task<string> Handle(UpdateOrganizationExtendRequest request,
        CancellationToken cancellationToken)
    {
        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        entity.ContactName = request.ContactName;
        entity.ContactPhoneNumber = request.ContactPhoneNumber;
        entity.Longitude = request.Longitude;
        entity.Latitude = request.Latitude;
        entity.Address = request.Address;
        entity.ExtendRemarks = request.ExtendRemarks;

        // 更新
        RegisterDirty(entity);

        return entity.Id!;
    }

    #endregion


    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbContext"></param>
    /// <param name="securityContextAccessor"></param>
    /// <param name="facadeResolver"></param>
    /// <param name="cacheManager"></param>
    /// <param name="configuration"></param>
    /// <param name="mapper"></param>
    /// <param name="dataPermission"></param>
    public OrganizationRequestHandler(ISqlSugarClient dbContext, ISecurityContextAccessor securityContextAccessor,
        IFacadeResolver facadeResolver, ICacheManager cacheManager, IConfiguration configuration,
        IMapsterMapper mapper, IDataPermission dataPermission) : base(dbContext, securityContextAccessor,
        facadeResolver, cacheManager, configuration, dataPermission)
    {
        _mapper = mapper;
    }
}